﻿namespace Rage.UI
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Media.Imaging;
    using System.Windows.Data;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows.Threading;
    using Microsoft.Win32;

    public partial class DG_ToRLoader_Schematic : ChildWindow
    {
        public DG_ToRLoader_Schematic()
        {
            InitializeComponent();

            DG_ProgressBar = new UI.DG_ProgressBar();
            DG_ProgressBar.Closed += new EventHandler(DG_ProgressBar_Closed);

            BackgroundWorker _backgroundWorker = new BackgroundWorker();

            // Set up the Background Worker Events
            _backgroundWorker.DoWork += _backgroundWorker_DoWork;
            _backgroundWorker.RunWorkerCompleted += _backgroundWorker_RunWorkerCompleted;

            // Run the Background Worker
            _backgroundWorker.RunWorkerAsync(250);

            // Create the thread and kick it started!
            //new Thread(start).Start();
            DG_ProgressBar.Show();
        }

        DG_ProgressBar DG_ProgressBar;

        List<GomLib.Models.Schematic> schems = new List<GomLib.Models.Schematic>();

        // Worker Method
        private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            // Do something
            
            //TorLib.Assets.assetPath = new OpenFileDialog() { @"D:\Program Files\Electronic Arts\BioWare\Star Wars-The Old Republic\Assets";

            GomLib.DataObjectModel.Load();
            var schemList = GomLib.DataObjectModel.GetObjectsStartingWith("schem.").Where(obj => !obj.Name.StartsWith("schem.mission")
                                                                                /*&& (obj.Name.StartsWith("schem.synthweaving"))*/);
            var schemVariationList = GomLib.Tables.SchematicVariationsPrototype.TableData;
            var itmModPkgList = GomLib.Tables.ItemModifierPackageTablePrototype.TableData;
            var itemBudget = GomLib.Tables.ItemBudget.TableData;
            double i = 0;
            double cntSkipped = 0, cntREd = 0;
            double ttl = schemList.Count();
            Dispatcher.BeginInvoke((Action) delegate {
                DG_ProgressBar.UpdateProgress(i, ttl, cntSkipped/*, itm.Name*/);
                //DG_ProgressBar.AddLineToLog(itm.Name + " : Completed");
            });
            foreach (var gomSchem in schemList)
            {
                GomLib.Models.Schematic schem = new GomLib.Models.Schematic();
                GomLib.ModelLoader.SchematicLoader.Load(schem, gomSchem);
                bool addIt = true;
                if (addIt) { if (schem.Deprecated) { addIt = false; } }
                if (addIt) {
                    if (schem.Item.Category == GomLib.Models.ItemCategory.Equipment
                        || schem.Item.Category == GomLib.Models.ItemCategory.Weapon)
                    {
                        if (schem.Item.RequiredLevel < 48)
                        {
                            addIt = false;
                        }
                    }
                    else if (schem.Item.Category == GomLib.Models.ItemCategory.Consumable
                        || schem.Item.Category == GomLib.Models.ItemCategory.Crafting
                        || schem.Item.Category == GomLib.Models.ItemCategory.ItemMod)
                    {
                        if (schem.Item.RequiredLevel < 40)
                        {
                            addIt = false;
                        }
                    }
                }
                if (addIt) {
                    if (schem.Item.Binding == GomLib.Models.ItemBindingRule.Pickup)
                    {
                        addIt = false;
                    }
                }
                // Parse Reverse Engineering Schematics
                if (addIt && schemVariationList.ContainsKey(schem.NodeId))
                {
                    var schemVars = schemVariationList[(ulong)schem.NodeId];
                    foreach(KeyValuePair<int, int> kvp in schemVars)
                    {
                        int varId = kvp.Key;
                        int prefixId = kvp.Value;
                        string prefixName = GomLib.Tables.ModificationNames.GetName(GomLib.Tables.ItemModifierPackageTablePrototype.GetModPkgNameId((long)prefixId));
                        var statStuff = GomLib.Tables.ItemModifierPackageTablePrototype.GetModPkgStatValues(prefixId);
                        GomLib.Models.Schematic schemVar = schem.Clone();
                        schemVar.Item.Name = prefixName.Replace("<<1>>", schemVar.Item.Name);
                        schemVar.Item.ModifierSpec = prefixId;
                        schemVar.Item.Id = (ulong)schem.Item.Id * (ulong)10000 + (ulong)prefixId;
                        schemVar.ItemId = (ulong)schemVar.Item.Id;
                        schemVar.Id = (ulong)schemVar.Item.Id;
                        if (schemVar.Item.Quality == GomLib.Models.ItemQuality.Premium) {
                            switch (varId) {
                                case 1: case 2: case 3:
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Prototype;
                                    schemVar.ItemParentId = (ulong)schem.Item.Id;
                                    break;
                                }
                                case 16: case 17: case 14: case 15: // parent is 3: Redoubt
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[3];
                                    break;
                                }
                                case 9: case 10: case 12: case 11: case 13: // parent is 2: Overkill
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[2];
                                    break;
                                }
                                case 08: case 04: case 06: case 07: case 05: // parent is 1: Critical
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[1];
                                    break;
                                }
                                default: { break; }
                            }
                        } else if (schemVar.Item.Quality == GomLib.Models.ItemQuality.Prototype) {
                            switch (varId) {
                                case 1: case 2: case 3:
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.ItemParentId = (ulong)schem.Item.Id;
                                    break;
                                }
                                case 16: case 17: case 14: case 15: // parent is 3: Redoubt
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[3];
                                    break;
                                }
                                case 9: case 10: case 12: case 11: case 13: // parent is 2: Overkill
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[2];
                                    break;
                                }
                                case 08: case 04: case 06: case 07: case 05: // parent is 1: Critical
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[1];
                                    break;
                                }
                                default: { break; }
                            }
                        } else if (schemVar.Item.Quality == GomLib.Models.ItemQuality.Artifact) {
                            switch (varId) {
                                case 1: case 2: case 3:
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.ItemParentId = (ulong)schem.Item.Id;
                                    break;
                                }
                                case 16: case 17: case 14: case 15: // parent is 3: Redoubt
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[3];
                                    break;
                                }
                                case 9: case 10: case 12: case 11: case 13: // parent is 2: Overkill
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[2];
                                    break;
                                }
                                case 08: case 04: case 06: case 07: case 05: // parent is 1: Critical
                                {
                                    schemVar.Item.Quality = GomLib.Models.ItemQuality.Artifact;
                                    schemVar.Item.Name += " [Superior]";
                                    schemVar.ItemParentId = (ulong)schem.Item.Id * 10000 + (ulong)schemVars[1];
                                    break;
                                }
                                default: { break; }
                            }
                        }
                        foreach (KeyValuePair<object, object> kvp2 in statStuff)
                        {
                            bool foundIt = false;
                            int budgetFromStatKVP = (int)(long)kvp2.Value - 1;
                            int budget2 = GomLib.Tables.ItemBudget.TableData[(int)schemVar.Item.Quality][schemVar.Item.ItemLevel - 1][budgetFromStatKVP];
                            foreach (GomLib.Models.ItemStat itmstat in schemVar.Item.StatModifiers)
                            {
                                if (itmstat.Stat == GomLib.Models.StatExtensions.ToStat((GomLib.ScriptEnum)kvp2.Key))
                                {
                                    itmstat.Modifier += budget2;
                                    foundIt = true;
                                }
                            }
                            if (!foundIt)
                            {
                                schemVar.Item.StatModifiers.Add(new GomLib.Models.ItemStat() {
                                    Stat = GomLib.Models.StatExtensions.ToStat((GomLib.ScriptEnum)kvp2.Key),
                                    Modifier = budget2,
                                });
                            }
                        }
                        schems.Add(schemVar);
                        cntREd++;
                    }
                }
                //
                if (addIt) { schem.ItemId = (ulong)schem.Item.Id; schem.ItemParentId = (ulong)0; schems.Add(schem); } else { cntSkipped++; }
                Dispatcher.BeginInvoke((Action) delegate {
                    DG_ProgressBar.UpdateProgress(i, ttl, cntSkipped);
                });
                i++;
            }
            schems = schems.OrderBy(obj => obj.CrewSkillId).ThenBy(obj => obj.CraftingTime).ToList();
            view = new ListCollectionView(schems);
            WriteCode();
            //view.GroupDescriptions.Add(new PropertyGroupDescription("Category"));
            //view.GroupDescriptions.Add(new PropertyGroupDescription("SubCategory"));
            //view.GroupDescriptions.Add(new PropertyGroupDescription("ItemLevel"));
            //view.SortDescriptions.Add(new SortDescription("Id", ListSortDirection.Ascending));
            //view.SortDescriptions.Add(new SortDescription("SubCategory", ListSortDirection.Ascending));
        }
        ListCollectionView view;

        // Completed Method
        private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled) {
                DG_ProgressBar.statusText.Text = "Cancelled";
            } else if (e.Error != null) {
                DG_ProgressBar.statusText.Text = "Exception Thrown";
            } else {
                DG_ProgressBar.statusText.Text = "Completed";
            }
            Dispatcher.BeginInvoke((Action)delegate
            {
                DG_ProgressBar.FinishProgress();
            });
            //DG_ProgressBar.BT_Cancel.IsEnabled = false;
            Dispatcher.BeginInvoke((Action)delegate
            {
                ItemGrid.ItemsSource = view;
            });
        }

        public void WriteCode()
        {
            string s = "";
            s += @"using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;

namespace SilenceOfTheEPGP.Classes
{
    public partial class Schematic
    {
        public static readonly List<Schematic> ALL_SCHEMATICS = new List<Schematic>()
        {
";
            int i = 0;
            string source = ""
                + "CraftingTime = {" + i++ + "}, CraftingTimeT1 = {" + i++ + "}, CraftingTimeT2 = {" + i++ + "}, CraftingTimeT3 = {" + i++ + "}, CrewSkillId = \"{" + i++ + "}\", Deprecated = {" + i++ + "}, DisableCritical = {" + i++ + "}, DisableDisassemble = {" + i++ + "}, "
                + "Fqn = \"{" + i++ + "}\", Id = {" + i++ + "}, Item = \"{" + i++ + "}\", Mat1 = \"{" + i++ + "}\", Mat1Quantity = {" + i++ + "}, Mat2 = \"{" + i++ + "}\", Mat2Quantity = {" + i++ + "}, Mat3 = \"{" + i++ + "}\", Mat3Quantity = {" + i++ + "}, Mat4 = \"{" + i++ + "}\", Mat4Quantity = {" + i++ + "}, Mat5 = \"{" + i++ + "}\", "
                + "Mat5Quantity = {" + i++ + "}, MissionCost = {" + i++ + "}, MissionDark = {" + i++ + "}, MissionDarkCrit = {" + i++ + "}, MissionDescription = \"{" + i++ + "}\", MissionDescriptionId = {" + i++ + "}, MissionFaction = \"{" + i++ + "}\", MissionLight = {" + i++ + "}, "
                + "MissionLightCrit = {" + i++ + "}, MissionUnlockable = {" + i++ + "}, MissionYieldDescription = \"{" + i++ + "}\", MissionYieldDescriptionId = {" + i++ + "}, Name = \"{" + i++ + "}\", NameId = {" + i++ + "}, NodeId = {" + i++ + "}, Research1 = \"{" + i++ + "}\", "
                + "Research2 = \"{" + i++ + "}\", Research3 = \"{" + i++ + "}\", ResearchChance1 = \"{" + i++ + "}\", ResearchChance2 = \"{" + i++ + "}\", ResearchChance3 = \"{" + i++ + "}\", ResearchQuantity1 = {" + i++ + "}, ResearchQuantity2 = {" + i++ + "}, ResearchQuantity3 = {" + i++ + "}, "
                + "SkillGreen = {" + i++ + "}, SkillGrey = {" + i++ + "}, SkillOrange = {" + i++ + "}, SkillYellow = {" + i++ + "}, Subtype = \"{" + i++ + "}\", TrainingCost = {" + i++ + "}, Workstation = \"{" + i++ + "}\", "
                + "ItemId = {" + i++ + "}, ItemParentId = {" + i++ + "}";
            foreach(GomLib.Models.Schematic schem in schems) {
            s += "            new Schematic() { " + string.Format(source ,
                schem.CraftingTime, schem.CraftingTimeT1, schem.CraftingTimeT2, schem.CraftingTimeT3, schem.CrewSkillId, schem.Deprecated.ToString().ToLower(), schem.DisableCritical.ToString().ToLower(), schem.DisableDisassemble.ToString().ToLower(),
                schem.Fqn, schem.Id, schem.Item, schem.Mat1, schem.Mat1Quantity, schem.Mat2, schem.Mat2Quantity, schem.Mat3, schem.Mat3Quantity, schem.Mat4, schem.Mat4Quantity, schem.Mat5,
                schem.Mat5Quantity, schem.MissionCost, schem.MissionDark, schem.MissionDarkCrit, schem.MissionDescription, schem.MissionDescriptionId, schem.MissionFaction, schem.MissionLight,
                schem.MissionLightCrit, schem.MissionUnlockable.ToString().ToLower(), schem.MissionYieldDescription, schem.MissionYieldDescriptionId, schem.Name, schem.NameId, schem.NodeId, schem.Research1,
                schem.Research2, schem.Research3, schem.ResearchChance1, schem.ResearchChance2, schem.ResearchChance3, schem.ResearchQuantity1, schem.ResearchQuantity2, schem.ResearchQuantity3,
                schem.SkillGreen, schem.SkillGrey, schem.SkillOrange, schem.SkillYellow, schem.Subtype, schem.TrainingCost, schem.Workstation, schem.ItemId, schem.ItemParentId
                ) + "},\n";
            }
            s += "        };\n";
            s += "    }\n";
            s += "}\n";
            s = s.Replace(" Empty List", "").Replace(", \", ", "\", ");
            Dispatcher.BeginInvoke((Action)delegate
            {
                TB_Code.Text = s;
            });
        }

        private void DG_ProgressBar_Closed(object sender, EventArgs e)
        {
            LB_Count.Text = DG_ProgressBar.TB_Perc.Text;
        }

        private Dictionary<object, Exception> errors = new Dictionary<object, Exception>();

        private void OKButton_Click(object sender, RoutedEventArgs e) { this.DialogResult = true; }
    }
}

